结果
算术运算符的结果类型由一组称做“普通算术转换”的规则确定(C.6.3节)。这里的整体目的就是让产生的结果具有“最大的”运算对象类型。举例来说,如果某个二元运算符的一个运算对象是浮点数,那么计算就将通过浮点算术完成,结果的类型是浮点数值。如果有一个long运算对象,那么计算就用长整数算术,结果就是long。比int小的运算对象(例如,bool和char)在运算符作用之前都将被转换到int。
关系运算符,==、<=等产生布尔值。用户定义运算符的意义及其结果类型依赖于它们的声明(11.2节)。
只要逻辑上可行,一个以左值作为运算对象的运算符的结果,仍然是指称这个左值对象的左值,例如,
void f(int x, int y)
{
int j = x = y; // x = y的值是赋值后x的值
int* p = &++x; // p指向x
int* q = &(x++); // 错误❌:x++不是一个左值(它不是存储在x里的值)
int* pp = &(x>y?x:y); // 较大的那个int的地址
}
如果?:的第二和第三个运算对象都是左值且具有相同的类型,结果将具有这个类型而且是一个左值。以这种方式保存左值将使运算符的使用具有最大的灵活性。对于写出一些代码,使它们能以统一而有效的方式工作在内部类型和用户定义类型上,这种规定就特别有用处(例如,在写模板或者生成C++代码的程序时)。
sizeof的结果是一个无符号整型size_t,这个类型在< cstddef > 里定义。指针减的结果是一个有符号的整型ptrdiff_t,也在< cstddef >里定义。
实现不必检查算术溢出,实际上也很难做。例如,
void f()
{
int i = 1;
while(0 < i) i++;
cout << "i has become negative!" << i << '\n';
}
将(最终)试图去增加i,使之超出最大的整数。这时会发生什么是无定义的,但典型情况是那个值被“卷回来”变成一个负数(在我的机器上得到-2147483648)。与此类似,除零的结果也是无定义的,但这样做通常将导致程序的突然终止。特别要指出的是,下溢、上溢和除零都不会抛出标准异常(14.10节)。
🔚